#include "stdafx.h"
#include "GUI.h"
#include "..\Window.h"

#include "..\..\Global\globaldef.h"

Render::tResource* GUI::g_pCursor = NULL;
D3DXVECTOR2 GUI::g_CursorPosition = D3DXVECTOR2(0,0);
GUI::tStamp GUI::g_CursorRect = {0,0,0,0};
std::vector<GUI::Components::Dialog*> GUI::g_Dialogs;

const uint GUI::CONSOLE_LINES = 5;
const uint GUI::CONSOLE_SPEED = 100;
std::string GUI::g_Console[GUI::CONSOLE_LINES];
uint GUI::g_ConsoleType[GUI::CONSOLE_LINES];
uint GUI::g_ConsoleTimer = 0;
bool GUI::g_CursorEnabled = false;

void GUI::StampGetPixel(GUI::tStamp* pStamp, RECT* pOut) {

	if(pOut && pStamp) {

		RECT window;
		CWindow::GetClientRectangle(&window);
		uint height = window.bottom - window.top;
		uint width = window.right - window.left;

		pOut->top = pStamp->top * height;
		pOut->bottom = pStamp->bottom * height;
		pOut->right = pStamp->right * width;
		pOut->left = pStamp->left * width;
	}
}

void GUI::StampGetPixel(Render::tResource* pTexture, RECT* pOut) {

	if(pOut && pTexture) {
		UINT w,h;
		Render::Singleton()->GetTextureInfo(pTexture, &w, &h);

		pOut->top = 0;
		pOut->bottom = h;
		pOut->right = w;
		pOut->left = 0;
	}
}

void GUI::StampGetPercentage(RECT* pStamp, GUI::tStamp* pOut) {

	if(pOut && pStamp) {

		RECT window;
		CWindow::GetClientRectangle(&window);
		uint height = window.bottom - window.top;
		uint width = window.right - window.left;

		pOut->top = (float)pStamp->top / (float)height;
		pOut->bottom = (float)pStamp->bottom / (float)height;
		pOut->right = (float)pStamp->right / (float)width;
		pOut->left = (float)pStamp->left / (float)width;
	}
}

void GUI::ScaleToWindow(int x, int y, D3DXVECTOR2* pOutput) {

	if(pOutput) {

		RECT window;
		CWindow::GetClientRectangle(&window);
		pOutput->x = (float)x / float(window.right - window.left);
		pOutput->y = (float)y / float(window.bottom - window.top);
	}
}

void GUI::FracToWindow(float x, float y, D3DXVECTOR2* pOutput) {

	if(pOutput) {

		RECT window;
		CWindow::GetClientRectangle(&window);
		pOutput->x = x * float(window.right - window.left);
		pOutput->y = y * float(window.bottom - window.top);
	}
}

void GUI::StampCreate(const int left, const int top, const int width, const int height, RECT* pOut) {

	if(pOut) {

		pOut->left = left;
		pOut->right = left + width;
		pOut->top = top;
		pOut->bottom = top + height;
	}
}

bool GUI::StampContainsPoint(GUI::tStamp* pStamp, D3DXVECTOR2 stampOffset, const float x, const float y) {

	if(!pStamp)
		return false;

	float w = pStamp->right - pStamp->left;
	float h = pStamp->bottom - pStamp->top;

	if(x < stampOffset.x)
		return false;
	if(x > w + stampOffset.x)
		return false;
	
	if(y < stampOffset.y)
		return false;
	if(y > h + stampOffset.y)
		return false;

	return true;
}

float GUI::Width(GUI::tStamp* pRect) {

	if(pRect) {

		if(pRect->right > pRect->left) 
			return pRect->right - pRect->left;
	}

	return 0;
}

float GUI::Height(GUI::tStamp* pRect) {

	if(pRect) {

		if(pRect->bottom > pRect->top) 
			return pRect->bottom - pRect->top;
	}

	return 0;
}

GUI::GUI() {
 
}

GUI::~GUI() {
	Release();
}

bool GUI::Create() {

	Render::tResource* pCursor = NULL;

	try {

		//if(!Render::Singleton()->CreateTexture("GUI\\buttons_main.jpg", &pButtonsMain))
		//	throw tException("Failed to create buttons texture");

		if(!Render::Singleton()->CreateTexture("GUI\\lv_cursor.png", &pCursor))
			throw tException("Failed to create buttons texture");

		/*Render::Singleton()->ReleaseResource(&GUI::Main::g_pButtonSet);*/
		Render::Singleton()->ReleaseResource(&GUI::g_pCursor);

		if(!GUI::Main::Create())
			throw tException("Failed to create main menu");
		
		RECT cursorRect = {0,0,12,18};
		GUI::StampGetPercentage(&cursorRect, &GUI::g_CursorRect);
		GUI::g_pCursor = pCursor;
		return true;

	}catch(tException e) {

		Render::Singleton()->ReleaseResource(&pCursor);
		
		std::string message;
		tException::GetMessage(&e, message);
		return false;
	}
}

bool GUI::Release() {
	
	/*for(u_int i = 0; i < m_panels.size(); i++) {
		m_panels[i]->Release();
		delete m_panels[i];
	}
	m_panels.clear();*/

	GUI::Main::Release();
	Render::Singleton()->ReleaseResource(&GUI::g_pCursor);
	
	return S_OK;
}

void GUI::EnableCursor(bool enabled) {

	GUI::g_CursorEnabled = enabled;
}

void GUI::PokeMouse() {

	GUI::OnMouseEvent(0, 0, GUI::MouseButton::BUTTON_UP, GUI::MouseButton::BUTTON_UP);
}

void GUI::OnMouseEvent(const int x, const int y, const GUI::MouseButton left, const GUI::MouseButton right) {

	if(GUI::g_CursorEnabled) {

		GUI::g_CursorPosition.x += x * 0.001f;
		GUI::g_CursorPosition.y += y * 0.001f;

		RECT window;
		GUI::tStamp percWindow;
		CWindow::GetClientRectangle(&window);
		GUI::StampGetPercentage(&window, &percWindow);

		if(GUI::g_CursorPosition.x < percWindow.left)
			GUI::g_CursorPosition.x = percWindow.left;
		if(GUI::g_CursorPosition.x > percWindow.right - GUI::g_CursorRect.right)
			GUI::g_CursorPosition.x = percWindow.right - GUI::g_CursorRect.right;

		if(GUI::g_CursorPosition.y < percWindow.top)
			GUI::g_CursorPosition.y = percWindow.top;
		if(GUI::g_CursorPosition.y > percWindow.bottom - GUI::g_CursorRect.bottom)
			GUI::g_CursorPosition.y = percWindow.bottom - GUI::g_CursorRect.bottom;

		GUI::Main::OnMouseEvent(GUI::g_CursorPosition.x, GUI::g_CursorPosition.y, left, right);
		
		FOREACH(Components::Dialog*, i, GUI::g_Dialogs)
			(*i)->OnMouseEvent(GUI::g_CursorPosition.x, GUI::g_CursorPosition.y, left, right);
	}
}

void GUI::OnKeydown(UINT* pKeyboardState) {

}

void GUI::Update() {

	if(g_ConsoleTimer == 0) {
	
		for(uint i = GUI::CONSOLE_LINES - 1; i > 0; i--) {
			GUI::g_Console[i] = GUI::g_Console[i - 1];
			GUI::g_ConsoleType[i] = GUI::g_ConsoleType[i - 1];
		}
		GUI::g_Console[0].clear();
		GUI::g_ConsoleType[0] = 0;

		g_ConsoleTimer = GUI::CONSOLE_SPEED;
	}
	else {

		g_ConsoleTimer --;
	}

	for(uint i = 0; i < GUI::g_Dialogs.size(); i++) {

		GUI::Components::Dialog *pDlg = GUI::g_Dialogs[i];
		if(pDlg->m_dispose) {
			GUI::g_Dialogs.erase(GUI::g_Dialogs.begin() + i);
			delete pDlg;
			i--;
		}
		else
			pDlg->Update();

	}

	GUI::Main::Update();
}

void GUI::DrawConsole() {

	for(uint i = 0; i < GUI::CONSOLE_LINES; i++) {
		
			float t = (GUI::CONSOLE_LINES - (i + 1));
			D3DXVECTOR2 p;
			p.x = 0.0151f;
			p.y = 0.045f + 0.025 * t;

			t /= (float)GUI::CONSOLE_LINES;

			uint hi = 255 * t;
			uint lo = 125 * t;

			D3DCOLOR color;
			switch(GUI::g_ConsoleType[i]) {
				default:				
				case 0:
					color = D3DCOLOR_RGBA(hi, hi, hi, 255);
					break;
				case 1:
					color = D3DCOLOR_RGBA(hi, lo, lo, 255);
					break;
				case 2: 
					color = D3DCOLOR_RGBA(hi, hi, lo, 255);
					break;
			}

			Render::Singleton()->DrawString(0, color, p, (char*)GUI::g_Console[i].c_str());
		}
}

void GUI::Draw() {
	
	if(Render::Singleton()->BeginSprites()) {


		GUI::DrawConsole();
		GUI::Main::Draw();

		FOREACH(Components::Dialog*, i, GUI::g_Dialogs)
			(*i)->Draw();

		if(GUI::g_CursorEnabled) {
		
			RECT r = {0,0,12,18};
			Render::Singleton()->DrawSprite(GUI::g_pCursor,  GUI::g_CursorPosition, D3DXVECTOR2(1,1), &r);
		}

		Render::Singleton()->EndSprites();

	
	}
	


}

void GUI::PrintMessage(const char* format, ...) {

	char Buffer[512] = {'\0'};

	va_list	args; 
	va_start (args,format); 
	vsprintf_s(Buffer, 512,format,args); 
	perror(Buffer); 
	va_end(args); 

	for(uint i = GUI::CONSOLE_LINES - 1; i > 0; i--) {

		GUI::g_Console[i] = GUI::g_Console[i - 1];
		GUI::g_ConsoleType[i] = GUI::g_ConsoleType[i - 1];
	}
	
	GUI::g_Console[0] = Buffer;
	GUI::g_ConsoleType[0] = 0;
	g_ConsoleTimer = GUI::CONSOLE_SPEED;
}

void GUI::PrintWarning(const char* format, ...) {

	char Buffer[512] = {'\0'};

	va_list	args; 
	va_start (args,format); 
	vsprintf_s(Buffer, 512,format,args); 
	perror(Buffer); 
	va_end(args); 

	for(uint i = GUI::CONSOLE_LINES - 1; i > 0; i--) {

		GUI::g_Console[i] = GUI::g_Console[i - 1];
		GUI::g_ConsoleType[i] = GUI::g_ConsoleType[i - 1];
	}
	
	GUI::g_Console[0] = std::string("WAR: ") + std::string(Buffer);
	GUI::g_ConsoleType[0] = 2;
	g_ConsoleTimer = GUI::CONSOLE_SPEED;
}

void GUI::PrintError(const char* format, ...) {

	char Buffer[512] = {'\0'};

	va_list	args; 
	va_start (args,format); 
	vsprintf_s(Buffer, 512,format,args); 
	perror(Buffer); 
	va_end(args); 

	for(uint i = GUI::CONSOLE_LINES - 1; i > 0; i--) {

		GUI::g_Console[i] = GUI::g_Console[i - 1];
		GUI::g_ConsoleType[i] = GUI::g_ConsoleType[i - 1];
	}
	
	GUI::g_Console[0] = std::string("ERR: ") + std::string(Buffer);
	GUI::g_ConsoleType[0] = 1;
	g_ConsoleTimer = GUI::CONSOLE_SPEED;
}